import axios from 'axios'
import Vue from 'vue'
import { restUrl as baseUrl } from '@/config'
import { codeHeaders, encryptBody } from '@/tool/sm.js'
import notification from 'ant-design-vue/es/notification'
import store from '../store'
import { unionApiUrl } from '@/api/config'
import { BUSINESS_MENU_TYPE } from '@/config/businessConfig'
import { getUrlParam } from '@/utils/util'

// 三个业务菜单下的接口需要额外传的参数
const businessAdditionalQuery = (type) => {
  const activeCodes = store.state.user.activeCodes
  const businessSearchConditions = store.state.user.businessSearchConditions
  let queryType
  Object.keys(BUSINESS_MENU_TYPE).forEach(key => {
    if(activeCodes.some(item => item === BUSINESS_MENU_TYPE[key].code)){
      queryType = key
    }
  })
  // 审批页面默认 queryType = 1
  if(getUrlParam('taskDefKey') || getUrlParam('procInstId') || getUrlParam('type') === 'approve'){
    queryType = 1
  }
  if(!queryType) return undefined
  if(queryType == 3){
    return {
      queryType,
      detSet: type === 'get' ? businessSearchConditions.detSet.join(',') : businessSearchConditions.detSet,
      orgSet: type === 'get' ? businessSearchConditions.orgSet.join(',') : businessSearchConditions.orgSet,
    }
  }else{
    return {
      queryType
    }
  }
}

//这里必须使用axios实例，因为已经有一个没有创建实例而直接使用的axio了，
// 在request.js，这里如果直接使用axios的话，request.js里面的拦截器也会执行
//创建一个实例再去使用这个实例请求，request.js里面的axios配置就不会生效
const instance = axios.create({
  baseURL: baseUrl,
  timeout: 600000,
  withCredentials: true
})
// request拦截器
instance.interceptors.request.use((config) => {
  //只针对删除接口：ids:[null]后端报错的情况。做一个统一处理把null去掉
  //触发条件：1、post或者put。2、data不为空并且不为string。3、data里面有ids这个字段并且类型为数组
  if (config.method === 'post' || config.method === 'put') {
    if (config.data) {
      let data = null
      if (typeof config.data === 'string') {
        try {
          data = JSON.parse(config.data)
        } catch (e) {
          //不是目标
        }
      } else {
        data = config.data
      }
      if (data && data['ids']) {
        let value = data['ids']
        if (typeof value === 'object') {
          let newValue = []
          value.map(v => {
            if (v !== 0 && v !== null && v !== undefined) {
              newValue.push(v)
            }
          })
          data['ids'] = newValue
          config.data = data
        }
      }
    }
    // 三个业务菜单下的接口需要额外添加数据筛选的字段
    const additionalQuery = businessAdditionalQuery()
    if(additionalQuery && !(config.data instanceof FormData)){
      if(config.data?.param && !Array.isArray(config.data?.param)){
        config.data.param = {
          ...config.data.param,
          ...additionalQuery,
        }
      }else if(config.data?.query && !Array.isArray(config.data.query)){
        config.data.query = {
          ...config.data.query,
          ...additionalQuery,
        }
      }else if(!Array.isArray(config.data)){
        config.data = {
          ...config.data,
          ...additionalQuery,
        }
      }
    }
  }

  // 如果没有设置Content-Type，默认application/json
  if (!config.headers['Content-Type']) {
    config.headers['Content-Type'] = 'application/json'
  }
  // 方法做防重返和防篡改
  // if (process.env.VUE_APP_ENCRYPTION === '1') {
  config = codeHeaders(config)
  config = encryptBody(config)
  // }
  // 每次发送请求之前判断vuex中是否存在token
  // 如果存在，则统一在http请求的header都加上token
  const token = Vue.getAcloudProvider().getAccessToken()
  if (token) {
    config.headers.Authorization = 'Bearer ' + token
  }
  return config
}, error => {
  return Promise.reject(error)
})

function responseProcess(response) {
  // console.log('response',response)
  /*
  * 响应成功的拦截器，主要是对data作处理，如果没有返回data，那么会添加一个data字段，并把response.data的内容合并到data里面，然后返回
  * */
  let { data } = response
  // console.log(response)
  let res = {}
  try {
    if (data.byteLength === 0) {
      res.code = 500
      notification.warn({ message: '提示', description: '没有状态为获取的数据可下载' })
    } else {
      res.data = data
      res.code = 200
    }
  } catch (e) {
    res.code = 500
    notification.error({ message: '提示', description: '请求失败，请稍后重试！' })
  }
  return res
}

/*
* 响应拦截器，目前的处理是，无论失败或者成功都会返回{ code: xxx, data: xxx }这种类型的数据，没有reject和抛error。
* 如果有问题，拦截器里会进行提示，然后返回{ code: Xxx, data:xxx }这种数据。在then里面总是会接收到
* */
instance.interceptors.response.use(
  response => {
    // console.log('response',response)
    /*
    * 响应成功的拦截器，主要是对data作处理，如果没有返回data，那么会添加一个data字段，并把response.data的内容合并到data里面，然后返回
    * */
    let { data } = response
    // console.log(response)
    if (data === undefined || data === null || data === '') {
      notification.error({ message: '提示', description: '请求失败，请稍后重试！' })
      return { code: 500, data: [] }
    } else if (typeof data === 'string') {
      return { code: 200, data }
    } else if (data instanceof Array) {
      return { code: 200, data }
    } else {
      if (data.data === undefined || data.data === null) {
        data.data = { ...data }
      }
      let resCode = data.code
      if (resCode) {
        try {
          resCode = Number(resCode)
        } catch (e) {
          data.code = resCode = 500
        }
        if (resCode === 0) {
          data.code = resCode = 200
        }
        if (resCode !== 200 && resCode !== 501) {   //501 特殊处理
          notification.error({
            message: '提示',
            description: response.data.msg || response.data.message || '请求失败，请稍后重试！'
          })
        }
      } else {
        data.code = 200
      }
      return data
    }
  },
  error => {
    // console.log('error', error)
    // console.log(error.response)
    // console.log(error.response.status)
    if (error.response === undefined) {
      notification.error({ message: '提示', description: '服务器响应超时' })
      return { code: 500, msg: '服务器响应超时', data: [] }
    }
    if (error.response.status >= 500) {
      if (error.response.data.code === '4003') {
        return error.response
      } else {
        notification.error({ message: '提示', description: '服务器出现错误' })
        return { code: 500, msg: '服务器响应超时', data: [] }
      }

    }
    if (error.response.status === 404) {
      notification.error({ message: '提示', description: '接口不存在' })
      return { code: 404, msg: '接口不存在', data: [] }
    }
    if (error.response.status === 400) {
      notification.error({ message: '提示', description: '接口报错' })
      return { code: 400, msg: '接口报错', data: [] }
    }
    if (error.response.status === 401) {
      store.dispatch('SetHasRouters', false)
      // 退出登录
      Vue.getAcloudProvider().logout()
      return { code: 401, msg: 'TOKEN失效，请重新登录', data: [] }
    } else {
      let { data } = error.response
      if (data === null || data === undefined) {
        notification.error({ message: '提示', description: '请求失败，请稍后重试！' })
        return { code: 200, data: [] }
      } else {
        let resCode = data.code
        if (data.data === undefined || data.data === null) {
          data.data = { ...data }
        }
        if (resCode && typeof resCode == 'number' && resCode !== 200) {
          notification.error({ message: '提示', description: response.data.message || '请求失败，请稍后重试！' })
        } else {
          data.code = 200
        }
        return data
      }
    }
  })

export default instance

export function get(url, params = {}) {
  return new Promise((resolve, reject) => {
    axios
      .get(url, { params: params })
      .then(response => {
        resolve(response)
      })
      .catch(err => {
        reject(err)
      })
  })
}

export function downloadGet(url, data, params = {}) {
  return axios.get(url, { params, responseType: 'arraybuffer' })
    .then(function (response) {
      let disposition = response.headers['content-disposition']
      let filenameType = disposition.substr(disposition.indexOf('filename') + 9)
      let filename = Date.now()
      switch (filenameType) {
        case '1':
          filename = '其他资产'
          break
        case '2':
          filename = '房屋建筑'
          break
        case '3':
          filename = '汽车'
          break
        case '4':
          filename = '低值易耗品'
          break
      }
      if (response.data.hasOwnProperty('code')) {
        this.$message.warning('导出错误')
        return
      }
      let blob = new Blob([response.data], { type: 'application/xls' })
      let link = document.createElement('a')
      link.href = window.URL.createObjectURL(blob)
      link.download = filename + '.xls'
      link.click()
    })
}

export function downloadGetDoc(url, data, params = {}) {
  return axios.get(url, { params, responseType: 'arraybuffer' })
    .then(function (response) {
      let filename = data || Date.now()
      let blob = new Blob([response.data], { type: 'application/doc' })
      let link = document.createElement('a')
      link.href = window.URL.createObjectURL(blob)
      link.download = filename + '.doc'
      link.click()
    })
}
export function downloadPost(url, data, params = {}, fileName) {
  return axios.post(url, data, { responseType: 'arraybuffer' })
    .then(function (response) {
      // let disposition = response.headers['content-disposition']
      let blob = new Blob([response.data], { type: 'application/xls' })
      let link = document.createElement('a')
      link.href = window.URL.createObjectURL(blob)
      link.download = fileName ? fileName : ('标准模板下载' + '.xlsx')
      link.click()
    })
}

export function downloadPost2(url, data, params = {}, fileName) {

  return axios.get(url, { params, responseType: 'arraybuffer' })
    .then(function (response) {
      let res = responseProcess(response)
      if (res.code === 200) {
        // let disposition = response.headers['content-disposition']
        let blob = new Blob([res.data], { type: 'application/xls' })
        let link = document.createElement('a')
        link.href = window.URL.createObjectURL(blob)
        link.download = fileName ? fileName : ('标准模板下载' + '.xlsx')
        link.click()
      }
    })
}


/**
 * post request
 * @param url
 * @param data
 * @param time 超时时间
 * @returns {Promise}
 */
export function post(url, data = {}, time) {
  return new Promise((resolve, reject) => {
    axios.post(url, data, time).then(
      response => {
        resolve(response)
      },
      err => {
        reject(err)
      }
    )
  })
}

/**
 * put request
 * @param url
 * @param data
 * @returns {Promise}
 */
export function put(url, data = {}) {
  return new Promise((resolve, reject) => {
    axios.put(url, data).then(
      response => {
        resolve(response)
      },
      err => {
        reject(err)
      }
    )
  })
}

/**
 * delete request
 * @param url
 * @param data
 * @returns {Promise}
 */
export function remove(url, data = {}) {
  return new Promise((resolve, reject) => {
    axios.delete(url, data).then(
      response => {
        resolve(response)
      },
      err => {
        reject(err)
      }
    )
  })
}

